<template>
    <div class="bi-table" ref="box">
        <div class="bi-table-header"  >
            <table :class="tableClass" :style="headerWidth" ref="header">
                <thead>
                    <tr class="bi-header-row">
                        <th class="checkbox" v-if="dragsort" valign="middle">
                            <i class="fa fa-arrows" title="拖动排序" />
                        </th>
                        <th class="checkbox" v-if="checkbox" valign="middle">
                            <input type="checkbox" class="form-check-input" v-model="checkAll">
                        </th>
                        <th v-if="radio" class="radio" valign="middle">
                            <bi-icon data="fa-ban" style="cursor: pointer;" @click="radioValue = null"></bi-icon>
                        </th>
                        <slot></slot>
                        <th class="bi-table-header-empty" v-if="heightScroll"></th>
                     </tr>
                </thead>
            </table>
        </div>
        
        <div  class="bi-table-body"  ref="body"  :style="scrollHeight"    >
            <table :class="tableClass" ref="tableContent" :style="tableWidth">
                <tbody v-if="!loading && !reload" ref="tableBody" >
                    <tr class="bi-body-row" v-for="(item,index) in list" :key="item.__id" :data-index="index" :data-id="item.__id" :data-drag="item[itemKey]" :data-parent="item.__parent"   :class="trClass(item)" >
                        <td class="checkbox" v-if="dragsort" valign="middle">
                            <div class="dragsort" draggable="true">
                                <i class="fa fa-ellipsis-v"></i>
                                <i class="fa fa-ellipsis-v"></i>
                            </div>
                        </td>
                        <td class="checkbox" v-if="checkbox" valign="middle">
                            <input type="checkbox" :value="item" :disabled="item.disabled" class="form-check-input" v-model="checkedList">
                        </td>
                        <td class="radio" v-if="radio" valign="middle">
                            <input type="radio"  :value="item" :disabled="item.disabled"  class="form-check-input" v-model="radioValue">
                        </td>
                        <slot></slot>
                    </tr>
                </tbody>
            </table>

            <div class="bi-table-more" v-if="loading || list.length == 0" :style="moreHeight">
                <div class="no-data" v-if="!loading && list.length == 0">{{noDatalabel}}</div>
                <bi-icon data="fa fa-spinner fa-spin"  v-if="loading"></bi-icon> 
            </div>
        </div>

       
    </div>
</template>

<script>
import dragsort from '../dragsort.js';
export default{
    
    provide(){
        return {
            addColumnWidth:(width)=>{
                if (width=='auto'){
                    this.columnAutoCount ++;
                }else{
                    this.columnWidth += parseInt(width);
                }
            },
            addColumnWidthUpdate:(type,minWidth,update)=>{
                this.columnWidthUpdateList.push({type,minWidth:parseInt(minWidth),update});   
            },
            updateFold:(id,itemKey,fold)=>{
                let foldList = this.getFoldData();
                foldList[itemKey] = fold;
                this.switchFold(id,fold);
                if (this.storagename)  localStorage.setItem(this.storagename,JSON.stringify(foldList));
                
            },
            tree:this.tree,
            itemKey:this.itemKey
        }
    },
    data(){

        //随机一个id
        let id = Math.random().toString(36).substr(2, 9);

        return {
            id,
            __bi_table:true,
            __data:[],
            columnWidth:0,
            columnAutoCount:0,
            columnWidthUpdateList:[],
            bodyWidth:0,
            boxWidth:0,
            heightScroll:false,
            list:this.flashData(this.data),
            checkAll:false,
            checkedList:[],
            radioValue:null,
            reload:false,
            _dataChange:false
        }
    },
    watch:{
        data(value){
           this.__data = JSON.parse(JSON.stringify(value));
           this.list = this.flashData(this.__data);
           
           this.$nextTick(()=>{
                this._dataChange = true;
                this.$forceUpdate();
           });
        },
        checkAll(value){
             if (value){
                this.checkedList = this.list;
            }else{
                this.checkedList = [];
            }
        },
        checkedList(value){
            if (value.length==this.list.length){
                this.checkAll = true;
            }else{
                this.checkAll = false;
            }
        },
        loading(value){
            if (!value){
                this.boxWidth = false;
            }
        },
        radioValue(value){
            this.$emit('radioChange',value);
        },
        checkedList(value){
            this.$emit('checkboxChange',value);
        },
        loading(){
            if (this.loading){
                this.checkedList = [];
                this.checkAll = false;
                this.radioValue = null;
                this.$emit('radioChange',null);
                this.$emit('checkboxChange',[]);
            }else{
                if (this.dragsort){
                   
                     this.$nextTick(()=>{
                        this.bindDragsort();
                    });
                }
            }
        }
        
    },
    methods:{
        bindDragsort(){
            let sourceNode;
            let drager  = new dragsort(this.$refs.tableBody,{
                callback:(value)=>{
                    
 
                    let parent = 0; 
                    
                    this.list.forEach(element => {
                        if (sourceNode.dataset.parent == element.__id){
                            parent = element[this.itemKey];
                        }
                    });
                     //找到data 的父节点

                    let findParent = (_data) =>{
                         for(let i in _data){
                            if (_data[i][this.itemKey] == parent){
                                _data[i]['children'] = sortList(_data[i]['children']);
                            }else{
                                if (_data[i]['children'] && _data[i]['children'].length>0){
                                    _data[i]['children'] = findParent(_data[i]['children']);
                                }
                            }
                       }
                       return _data;
                    }

                    let sortList =  (_data) =>{
                        let _sort = [];

                        for(let i=0;i<value.length;i++){
                            for(let j in _data){
                                if(value[i] == _data[j][this.itemKey]){                                               
                                    _sort.push(_data[j]);
                                }
                            }
                        }
                        //console.log(_sort);
                        return _sort;
                    }
                    
                    this.reload = true;
                    if (parent == 0){
                        this.__data =sortList(this.__data);
                    }else{
                        this.__data =findParent(this.__data);
                    }

                    this.$emit('dragsort',value);

                    this.list = this.flashData(this.__data);
                   
                    this.$nextTick(()=>{
                        this.reload = false;
                        this.$nextTick(()=>{
                            this.bindDragsort();
                        });
                    });
                    
                },
                start:(node)=>{
                    sourceNode = node;
                    if (this.tree){
                        let list = this.$refs.tableBody.getElementsByClassName(this.getClassName(node.dataset.id));

                        for (let i = 0; i < list.length; i++) {
                            let _node = list[i];
                            _node.classList.add('drager-move-more');
                        }
                    }
                        
                    return true;
                },
                move:()=>{
                    if (this.tree){
                        
                        
                        
                    }
                },
                filter:(node,target,dataTransfer)=>{
 
                    if (node.dataset.parent == target.dataset.parent){
                        return true;
                    }else{
                        dataTransfer.dropEffect = 'none';
                        return false;
                    }

                },
                end:(node,target)=>{
                    return  node.dataset.parent == target.dataset.parent;
                }
            });  
        },
        getFoldData(){

            let foldData = {};

            if (this.storagename!=''){

                let liststring = localStorage.getItem(this.storagename);
                if (liststring!=undefined && liststring!=''){
                    foldData =  JSON.parse(liststring);
                    
                }
            }

            return foldData;
        },
        switchFold(id,fold){
           
            let idstr = 'bi-table-'+this.id+'-tr-parent-'+id;
            let list = document.getElementsByClassName(idstr);
            
            if (list.length>0){
                for (let i=0;i<list.length;i++) list[i].style.display = !fold?'table-row':'none';
            }
        },
        flashData(_data){

            _data = JSON.parse(JSON.stringify(_data));
            let list = [];
            let foldData = this.getFoldData();
            let switchList  = [];
            let exportTree = (data,level = 0,parent="0",parents=[]) =>{
                let tr = 0
                for(let i in data){

                    let element =  data[i];

                    if (typeof element!='object' || element==null) continue;
                    
                    element.__key = i;
                    element.__level = level;
                    element.__id = parent +'_'+ tr.toString();
                    element.__parents = JSON.parse(JSON.stringify(parents));
                    element.__parents.push(parent);
                    element.__parent = (parent);
                    if (this.itemKey) {
                        
                        element.__fold = foldData[element[this.itemKey]] ??this.defaultFold;
                        
                        if (element.__fold){
                            switchList.push(element.__id);
                        }
                    }

                    list.push(element);
                    if (element.children && element.children.length > 0){
                        exportTree(element.children,level+1,element.__id,element.__parents);
                    }
                    tr ++;
                }
                
            }

            exportTree(_data);

            this.$nextTick(()=>{
                switchList.forEach(id=>{
                    this.switchFold(id,true);
                });
            });
            return list;
        },

        updateBoxWidth(boxWidth){
            let addWidth = 0;
            let autoWidth = this.getAutoWidth(boxWidth);
            this.columnWidthUpdateList.forEach(({type,minWidth,update})=>{
                if (autoWidth>minWidth){
                   if (type=='th') addWidth += autoWidth;
                    update(autoWidth);
                }else{
                    if (type=='th') addWidth += minWidth;
                    update(minWidth);
                }
            });
             //表格宽度
            if (this.checkbox ) addWidth += 30;
            if (this.radio) addWidth += 30;
            if (this.dragsort) addWidth += 30;
            this.bodyWidth = this.columnWidth + addWidth;
         
        },

        getAutoWidth(boxWidth){
             
            if (this.columnAutoCount == 0)  return 0;
            //根据table高度判断是否出现横向滚动条，减去宽度
            if (this.heightScroll){
                boxWidth -=  17;
            }

            let columnWidth = this.columnWidth; 
            if (this.checkbox ) columnWidth += 30;
            if (this.radio) columnWidth += 30;
            if (this.dragsort) columnWidth += 30;
            let residueWidth = boxWidth - columnWidth;
            let autoWidth = Math.floor(residueWidth/this.columnAutoCount);
            if (autoWidth<100) autoWidth = 100;
           
            return autoWidth;
        },
        getClassName(name){
            return 'bi-table-'+this.id+'-tr-parent-'+name;
        },
        trClass(item){
            let className = [];

            if (this.tree){
                item.__parents.forEach((el)=>{
                    //if (el!=='0'){
                        className.push(this.getClassName(el));
                    //}
                });
            }

            if (item.disabled){
                className.push('disabled');
            }
            
            return className;
        },
        updateHeightScroll(){
            if (this.height){
            //判断滚动高度是否大于默认高度
                let  height = parseInt(this.height);
                if (this.$refs.tableContent.offsetHeight>height){
                    this.heightScroll =  true;
                }else{
                    this.heightScroll =  false;
                }
            }
        }
    },
    updated(){
        this.updateHeightScroll();
    },
    mounted(){
        setInterval(()=>{
            if (this._dataChange || (this.$refs.box!=null  && this.$refs.box.clientWidth!=0 && this.$refs.box.clientWidth!=this.boxWidth )){
                this.updateHeightScroll();
                this.bodyWidth = this.$refs.box.clientWidth;     
                this.boxWidth = this.$refs.box.clientWidth;
                this.updateBoxWidth(this.bodyWidth);
                this._dataChange =  false;
            }
        },100);
        
        this.$refs.body.addEventListener("scroll", (e)=>{
            this.$refs.header.style.left = e.target.scrollLeft*-1 + 'px';
        });

        

        if (this.dragsort && this.el){
                this.$nextTick(()=>{
                this.bindDragsort();
            });
        }
    },
    computed:{
        tableClass(){
            let classList = [];
            classList.push('table')
            if (this.striped) classList.push('table-striped');
            if (this.dark) classList.push('table-dark');
            if (this.hover) classList.push('table-hover');
            if (this.bordered) classList.push('table-bordered');
            if (this.borderType) classList.push('border-'+this.borderType);
            return classList;
        },
        tableWidth(){
            let style = {};
            
            if (this.bodyWidth){
                style.width = parseInt( this.bodyWidth )+ 'px';
            }
            return style;
        },
        headerWidth(){
            let style = {};
            
            if (this.bodyWidth){

                let width  =  this.bodyWidth;
                if (this.heightScroll) width += 17;

                style.width = parseInt( width )+ 'px';
            }
            return style;
        }
        ,
        scrollHeight(){
            let style = {};
            if (this.height){
                style.height = parseInt(this.height) + 'px';
            }
            if (this.minHeight && this.minHeight != 'no'){
                style.minHeight = parseInt(this.minHeight) + 'px';
            }
            return style;
        },
        moreHeight(){
            let style = {};
            if (this.height){
                style.height = parseInt(this.height) + 'px';
            }
            if (this.minHeight && this.minHeight != 'no'){
                style.minHeight = parseInt(this.minHeight) + 'px';
            }
            return style;
        },
    },
    emits:['checkboxChange','radioChange','dragsort'],
    props:{
        data:{
            type:[Array,Object],
            default:[]
        },
        striped:{
            type:Boolean,
            default:false
        },
        dark:{
            type:Boolean,
            default:false
        },
        hover:{
            type:Boolean,
            default:false
        },
        bordered:{
            type:Boolean,
            default:false
        },
        borderType:{
            type:String,
            default:'default'
        },
        storagename:{
            type:String,
            default:''
        },
        itemKey:{
            type:String,
            default:''
        },
        height:{
            type:[String,Number],
            default:''
        },
        minHeight:{
            type:[String,Number],
            default:'no'
        },
        checkbox:{
            type:Boolean,
            default:false
        },
        radio:{
            type:Boolean,
            default:false
        },
        noDatalabel:{
            type:String,
            default:'NO DATA'
        },
        loading:{
            type:Boolean,
            default:false
        },
        tree:{
            type:Boolean,
            default:false
        },
        defaultFold:{
            type:Boolean,
            default:false
        },
        dragsort:{
            type:Boolean,
            default:false
        }
    }
}
</script>


<style>
.bi-table{
    width: 100%;
    overflow: hidden;
}

.bi-table .table{
    margin-bottom: 0;
}


.bi-table th{
    font-size: 14px;
}


.bi-table td{
    font-size: 14px;
    word-break: break-all;
    overflow: hidden;
}

.bi-table tr.disabled{
    opacity: 0.5;
}

.bi-table-header{
    width: 100%;
    margin-bottom: 0px;
    overflow: hidden;
    position: relative;

}
.bi-table-header table{
    position: relative;
}
.bi-table-body{
    width: 100%;
    overflow:auto;
}
.bi-table-body tr:first-child{
    border-top:none;
}
.bi-table-header .checkbox,
.bi-table-header .radio,
.bi-table-body .checkbox,
.bi-table-body .radio{
    width: 30px;
    padding: 0;
    margin: auto;
    line-height: 0;
    text-align: center;
}

.form-check-input{
    cursor: pointer;
}

.bi-table-more{
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bi-table-more .no-data{
    font-size: 16px;
    color:var(--bs-gray-400);
    font-weight:bold;
    min-height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.dragsort {
    color: var(--bs-gray-600);
    cursor: move;
}

.dragsort i + i {
    margin-left: 2px;
}

.drager-move td{
    background-color: rgba(0, 0, 0,0.1);
    opacity: 0.6;
}

.drager-move-more{
    display: none;
}

 

</style>